class myPromise {
	constructor(exe) {
		this.state = 'pending'
		this.value = undefined
		this.reason = undefined
		// 装所有成功/失败的回调函数
		this.onFullFilledCallBack = []
		this.onRejectedCallBack = []
		let resolve = (value) => {
			if (this.state === 'pending') {
				this.state = 'fullFilled'
				this.value = value
				this.onFullFilledCallBack.forEach((fn) => fn())
			}
		}
		let reject = (reason) => {
			if (this.state === 'pending') {
				this.state = 'rejected'
				this.reason = reason
				this.onRejectedCallBack.forEach((fn) => fn())
			}
		}

		try {
			exe(resolve, reject)
		} catch (error) {
			reject(error)
		}
	}

	then(onFullFilled, onRejected) {
		let x
		return new myPromise((resolve, reject) => {
			if (this.state === 'fullFilled') {
				try {
					x = onFullFilled(this.value)
					resolve(x)
				} catch (error) {
					reject(error)
				}
			}
			if (this.state === 'rejected') {
				try {
					x = onRejected(this.reason)
					reject(x)
				} catch (error) {
					reject(error)
				}
			}
			if (this.state === 'pending') {
				// 发布的时候循环执行里面的函数
				this.onFullFilledCallBack.push(() => {
					try {
						x = onFullFilled(this.value)
						resolve(x)
					} catch (error) {
						reject(error)
					}
				})
				this.onRejectedCallBack.push(() => {
					try {
						x = onRejected(this.reason)
						reject(x)
					} catch (error) {
						reject(error)
					}
				})
			}
		})
	}
	// static关键字，就表示该方法不会被实例继承，而是直接通过类来调用，这就称为“静态方法”。
	static resolve(value) {
		if (value instanceof myPromise) return value
		return new myPromise((resolve) => resolve(value))
	}

	// 使用场景：如果不知道一个值是否是Promise对象，使用Promise.resolve(value)
	// 来返回一个Promise对象,这样就能将该value以Promise对象形式使用。
	static reject(err) {
		if (err instanceof myPromise) return err
		return new myPromise((resolve, reject) => reject(err))
	}
	/*
    var p = Promise.reject('error')
    等同于
    var p = new Promise((resolve, reject) => reject('error'))
    */
	static race(list) {
		return new myPromise((resolve, reject) => {
			for (let p of list) {
				this.resolve(p).then(
					(res) => {
						resolve(res)
					},
					(err) => {
						reject(err)
					}
				)
			}
		})
	}
	static all(list) {
		return new myPromise((resolve, reject) => {
			let count = 0,
				values = [] //forEach里面不能写异步
			for (let [i, p] of list.entries()) {
				this.resolve(p).then(
					(res) => {
						count++
						values[i] = res
						if (count === list.length) resolve(values)
					},
					(err) => {
						reject(err)
					}
				)
			}
		})
	}
}

let p1 = new myPromise((resolve, reject) => {
	setTimeout(() => {
		resolve(1)
	}, 1000)
})
let p2 = new myPromise((resolve, reject) => {
	setTimeout(() => {
		resolve(2)
	}, 2000)
})
let p3 = new myPromise((resolve, reject) => {
	setTimeout(() => {
		reject(3)
	}, 3000)
})

let race = myPromise.race([p1, p2, p3])
race.then(
	(res) => {
		console.log(res, 'race')
	},
	(err) => {
		console.log(err, 'err_race')
	}
)

let all = myPromise.all([p1,p2,p3])
all.then(res=>{
    console.log(res,'all')
},err=>{
    console.log(err,'all')
})
new myPromise((resolve, reject) => {
	setTimeout(() => {
		resolve(10)
	}, 1000)
})
	.then(
		function (value) {
			console.log(value)
			return value + 1
		},
		function (reason) {
			console.log(reason)
		}
	)
	.then(
		function (value) {
			console.log(value)
			return a
		},
		function (reason) {
			console.log(reason)
		}
	)
	.then(
		function (value) {
			console.log(value)
		},
		function (reason) {
			console.log(reason)
		}
	)
